public class SolutionUserStoryIdea 
{
	
	//This method creates User Stories from solutions that meet a particular set of criteria.
	Public Static Void SolutionToUserStory(solution[] solutions)
	{
		
		//initially filter solutions from trigger as much as we can. We need solutions 
		//that are published, don't already have an associated user story, and send to Ideas is checked.
		List<string> solutionIdList = New List<string>();
		Map<Id, Solution> solutionMap = new Map<id, Solution>();
		for (integer i = 0; i < solutions.size(); i++)
		{
			if(solutions[i].status == 'reviewed')If(solutions[i].User_Story__c == Null)if(solutions[i].IsPublished == true)if(solutions[i].send_to_ideas__c==true)
			{
				solutionIdList.add(solutions[i].id);
				solutionMap.put(solutions[i].Id, solutions[i]);
			}
		}
		If(solutionIdList.size()>0)			
		{
			//Create a map to hold the category data
			Map<Id, string> categories = new Map<Id, string>();
	    	//select the category data for the solutions in the solutionId list
			For (CategoryData cd :[select RelatedSObjectid,CategoryNodeid from CategoryData where RelatedSObjectid in :solutionIdList])
			{
				if (categories.containsKey(cd.RelatedSObjectId)==false)
				{
					categories.put(cd.RelatedSObjectId,cd.categorynodeid);
				}	
			}
			Map<Id, string> categoryNames = new Map<Id, string>();
			For (CategoryNode cn :[select Id,MasterLabel from categoryNode where Id in (Select categorynodeid from categorydata where RelatedSobjectId in :categories.keyset())])
			{
				if (categoryNames.containsKey(cn.Id)==false)
				{
					categoryNames.put(cn.Id,cn.MasterLabel);
				}	
			}
			//finally we put it all together
			Map<Id,string>solutionRecordTypeMap = new Map<Id,string>();
			For(solution s:[select id,recordtype.name from solution where id in :solutionidlist])
			{
				solutionRecordTypeMap.put(s.id,s.recordtype.name);
			}
			List<User_Story__c> userStories = new List<User_Story__c>();
			for (integer x = 0; x < solutionIdList.size(); x++)
			{
				Solution UserStorySolution = solutionMap.get(solutionIdList[x]);
				user_story__c u = new user_story__c();
				u.name = UserStorySolution.SolutionName;
				//magical html stripper regex: '\\<.*?\\>'
				u.description__c = UserStorySolution.SolutionNote.replaceAll('\\<.*?\\>', '');
				If (categoryNames.get(categories.get(solutionIdList[x])) != Null)
				{
					u.category__c = categoryNames.get(categories.get(solutionIdList[x]));
				}
				else	
				{
					u.category__c = 'Other';
				}
				u.First_Observed_in_Release__c = UserStorySolution.Release__c;
				u.send_to_ideas__c = true;
				u.Status__c = 'CCB Review';
				u.Product__c = solutionRecordTypeMap.get(solutionIdList[x]);
				userStories.add(u);
			}
			insert userStories;
			//We need to put the id of the user story we just created on the originating solution
			List<solution> updateSolutions = new List<solution>();
			Map<id,id> solutionUserStoryMap = new Map<id,id>();
			for (integer x = 0; x < solutionIdList.size(); x++)
			{
				solutionUserStoryMap.put(solutionIdList[x],userStories[x].id);
			}	
			for (Solution s:[select Id,user_story__c from solution where Id in :solutionIdList])
			{
				s.User_Story__c = solutionUserStoryMap.get(s.id);
				s.Send_To_Ideas__c = false;
				updateSolutions.add(s);
			}
			update updateSolutions;	
			//all the cases associated with the originating solutions need to have their status changed to 
			//"User Story Submitted".
			List<case> updateCases = New List<case>();
			For(case c: [select Id,isclosed,status from Case where solution__c in :solutionIdList])
			{
				if(c.IsClosed == false)
				{
					c.status = 'User Story Submitted';
					updateCases.add(c);
				}
			}
			update UpdateCases;	
		}
		
	}
	
	Public static void IdeaToUserStory(idea[] ideas)
	{
		//initially filter ideas from trigger as much as we can. 
		List<string> ideaIdList = New List<string>();
		Map<Id, idea> ideaMap = new Map<id, idea>();
		for (integer i = 0; i < ideas.size(); i++)
		{
			If(ideas[i].User_Story__c == Null)if(ideas[i].send_to_solutions__c==true)
			{
				ideaIdList.add(ideas[i].id);
				ideaMap.put(ideas[i].Id, ideas[i]);
			}
		}
		If(ideaIdList.size()>0)			
		{
			Map<id,string> communityNameMap = new Map<id,string>();
			for(Community c:[select id,name from community])
			{
				communityNameMap.put(c.id,c.name);
			}
			List<User_Story__c> userStories = new List<User_Story__c>();
			for (integer x = 0; x < ideaIdList.size(); x++)
			{
				idea UserStoryIdea = ideaMap.get(ideaIdList[x]);
				user_story__c u = new user_story__c();
				u.name = UserStoryIdea.title;
				u.description__c = UserStoryIdea.Body;
				u.category__c = UserStoryIdea.Category;
				u.First_Observed_in_Release__c = UserStoryIdea.Observed_in_Release__c;
				u.send_to_solutions__c = true;
				u.product__c = communityNameMap.get(UserStoryIdea.CommunityId);
				u.idea_url__c = 'https://na6.salesforce.com/ideas/viewIdea.apexp?id=' + UserStoryIdea.Id;
				userStories.add(u);
			}
			insert userStories;
			//We need to put the id of the user story we just created on the originating idea
			List<idea> updateideas = new List<idea>();
			Map<id,id> ideaUserStoryMap = new Map<id,id>();
			for (integer x = 0; x < ideaIdList.size(); x++)
			{
				ideaUserStoryMap.put(ideaIdList[x],userStories[x].id);
			}	
			for (idea i:[select Id,user_story__c from idea where Id in :ideaIdList])
			{
				i.User_Story__c = ideaUserStoryMap.get(i.id);
				i.Send_To_Solutions__c = false;
				updateideas.add(i);
			}
			update updateideas;		
		}		
	}
	
	
	//creates an Idea from a user story. called by a before update trigger so we can perform validation to ensure we aren't creating multiple child ideas.
	Public static void UserStoryToIdea(User_Story__c[] UserStories)
	{
		
		List<string> userStoryIdList = New List<string>();
		Map<Id, User_Story__c> userStoryMap = new Map<id, User_Story__c>();
		for (integer i = 0; i < UserStories.size(); i++)
		{
			If(UserStories[i].send_to_ideas__c==true)If(UserStories[i].reviewed__c==true)If(UserStories[i].send_to_solutions__c==false)
			{
				userStoryIdList.add(UserStories[i].id);
				userStoryMap.put(UserStories[i].Id, UserStories[i]);
			}
		}
		If(userStoryIdList.size()>0)			
		{						
			Map<string,id> communityIdMap = new Map<string,id>();
			for(Community c:[select id,name from community])
			{
				communityIdMap.put(c.name,c.id);
			}
			List<idea> ideas = new List<idea>();
			for (integer x = 0; x < userStoryIdList.size(); x++)
			{
				User_Story__c IdeaUserStory = userStoryMap.get(userStoryIdList[x]);
				Idea i = new Idea();
				i.title = IdeaUserStory.name;
				i.body = IdeaUserStory.description__c;
				if(IdeaUserStory.category__c != null)
				{
					i.category = IdeaUserStory.Category__c;
				}
				else
				{
					i.Category = 'Other';
				}
				i.Observed_in_Release__c = IdeaUserStory.First_Observed_in_Release__c;
				If(communityIdMap.get(IdeaUserStory.product__c)!=null)
				{
					i.CommunityId = communityIdMap.get(IdeaUserStory.product__c);
				}
				else
				{
					i.CommunityId = communityIdMap.get('StackVision');
				}
				i.user_story__c = IdeaUserStory.Id;
				i.Workflow_Step__c = 'CCB Review';
				ideas.add(i);
			}
			insert ideas;	
			
			Map<id,id> UserStoryIdeaMap = new Map<id,id>();
			for (integer x = 0; x < userStoryIdList.size(); x++)
			{
				UserStoryIdeaMap.put(userStoryIdList[x],ideas[x].id);
			}	
			List<user_story__c> updateUserStories = new List<user_story__c>();
			for (User_Story__c u:[select Id from User_Story__c where Id in :userStoryIdList])
			{
				u.idea_url__c = 'https://na6.salesforce.com/ideas/viewIdea.apexp?id=' + UserStoryIdeaMap.get(u.id);
				u.Send_To_Ideas__c = false;
				updateUserStories.add(u);
			}
			update updateUserStories;		
		}				
	}
	//this method creates a solution from a user story that came from an idea.
	Public static void UserStoryToSolution(User_Story__c[] UserStories)
	{
		
		List<string> userStoryIdList = New List<string>();
		Map<Id, User_Story__c> userStoryMap = new Map<id, User_Story__c>();
		for (integer i = 0; i < UserStories.size(); i++)
		{
			If(UserStories[i].send_to_Solutions__c==true)If(UserStories[i].reviewed__c==true)If(UserStories[i].send_to_ideas__c==false)
			{
				userStoryIdList.add(UserStories[i].id);
				userStoryMap.put(UserStories[i].Id, UserStories[i]);
			}
		}
		If(userStoryIdList.size()>0)			
		{
			List<Solution> Solutions = new List<Solution>();
			for (integer x = 0; x < userStoryIdList.size(); x++)
			{
				User_Story__c SolutionUserStory = userStoryMap.get(userStoryIdList[x]);
				Solution s = new Solution();
				s.solutionName = SolutionUserStory.name;
				s.solutionNote = SolutionUserStory.description__c;
				s.Release__c = SolutionUserStory.First_Observed_in_Release__c;
				s.user_story__c = SolutionUserStory.Id;
				Solutions.add(s);
			}
			insert Solutions;	
			
			Map<Id,string> userStoryCategoryMap = New Map<id, string>();
			for (User_story__c u : [Select Id,Category__c from User_Story__c where id in :userStoryIdList])
			{
				userStoryCategoryMap.put(u.id, u.category__c);
			}
			List<CategoryNode> categoryNodeList = New List<CategoryNode>();
			for (CategoryNode cn : [Select Id,MasterLabel from categorynode])
			{
				categoryNodeList.add(cn);
			}
			List<CategoryData> category = New List<CategoryData>();
			for (integer x = 0; x < categoryNodeList.size(); x++)
			{
				for (integer i = 0; i < solutions.size(); i++)
				{
					If (userStoryCategoryMap.get(userStoryIdList[i]) == categoryNodeList[x].MasterLabel)
					{
						CategoryData cd = new CategoryData();
						cd.CategoryNodeId =	categoryNodeList[x].id;
						cd.RelatedSobjectId = solutions[i].Id;
						category.add(cd);
					}
				}
			}
			insert category;
			
			List<user_story__c> updateUserStories = new List<user_story__c>();
			for (User_Story__c u:[select Id from User_Story__c where Id in :userStoryIdList])
			{
				u.Send_To_Solutions__c = false;
				updateUserStories.add(u);
			}
			update updateUserStories;		
		}				
	}
	

}